﻿// Copyright (c) Matthias Koch
//
// See the NOTICE file distributed with this work for additional information
// regarding copyright ownership.  rubicon licenses this file to you under 
// the Apache License, Version 2.0 (the "License"); you may not use this 
// file except in compliance with the License.  You may obtain a copy of the 
// License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software 
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the 
// License for the specific language governing permissions and limitations
// under the License.
// 

using System;
using System.Linq;

using FluentAssertions;

using XValidation.Attributes;
using XValidation.Validations;

using Xunit;

namespace XValidation.UnitTests
{
  public class ValidationInfoProviderTest
  {
    public class GetValidationInfo
    {
      private readonly ValidationInfoProvider _provider;

      public GetValidationInfo ()
      {
        _provider = new ValidationInfoProvider();
      }

      [Fact]
      public void None ()
      {
        var method = typeof (DomainClass).GetMethods ().Single (x => x.Name == "Method1");
        var info = _provider.GetValidationItems (method);

        info.Should ().HaveCount (0);
      }

      [Fact]
      public void ArgumentSingle ()
      {
        var method = typeof (DomainClass).GetMethods ().Single (x => x.Name == "Method2");
        var info = _provider.GetValidationItems (method).Single ();

        info.ArgumentsIndex.Should ().Be (0);
        info.ParameterName.Should ().Be ("arg");
        info.Validations.Single ().Should ().BeOfType<NotNullValidation> ();
      }

      [Fact]
      public void ArgumentMultiple ()
      {
        var method = typeof (DomainClass).GetMethods ().Single (x => x.Name == "Method3");
        var info = _provider.GetValidationItems (method).Single ();

        info.ArgumentsIndex.Should ().Be (0);
        info.ParameterName.Should ().Be ("arg");
        info.Validations.Should ()
            .Contain (x => x.GetType () == typeof (NotNullValidation)).And
            .Contain (x => x.GetType () == typeof (NotEmptyValidation));
      }

      [Fact]
      public void Return ()
      {
        var method = typeof (DomainClass).GetMethods ().Single (x => x.Name == "Method4");
        var info = _provider.GetValidationItems (method).Single ();

        info.ArgumentsIndex.Should ().Be (-1);
        info.ParameterName.Should ().Be ("return");
        info.Validations.Single().Should ().BeOfType<NotNullValidation>();
      }

      private class DomainClass
      {
        public DomainClass ([NotEmpty] string arg)
        {
        }

        public void Method1 () { }

        public void Method2 ([NotNull] string arg) { }

        public void Method3 ([NotNull, NotEmpty] string arg) { }

        [return: NotNull]
        public string Method4 () { return null; }
      }
    }
  }
}